package com.mathmu.fetion.protocol;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.mathmu.IncompetentPlatformException;


public class Utility {
	public static final String domain = "fetion.com.cn";
	public static final String ssiDomain = "uid.fetion.com.cn";
	
	public static byte[] toHex(String text) {
		assert text.length() % 2 == 0;
		final int resultLength = text.length()/2;
		final byte[] result = new byte[resultLength];
		for (int i = 0; i < resultLength; ++i) {
			result[i] = Byte.parseByte(text.substring(i*2, i*2+2), 16);
		}
		return result;
	}
	
	public static String toText(byte[] hex) {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < hex.length; ++i) {
			buffer.append(String.format("%02x", hex[i]));
		}
		return buffer.toString();
	}
	
	public static byte[] SHA1Hash(byte[]... bytes) {
		try {
			final MessageDigest md = MessageDigest.getInstance("SHA-1");
			for (byte[] b : bytes) {
				md.update(b);
			}
			return md.digest();
		} catch (NoSuchAlgorithmException e) {
			throw new IncompetentPlatformException(e);
		}
	}

	public static byte[] toByteArray(String text) {
		// FIXME: what charset here?
		try {
			return text.getBytes("GBK");
		} catch (UnsupportedEncodingException e) {
			assert false;
			e.printStackTrace();
			return null;
		}
	}
	
	public static String hashPasswordV1(byte[] b0, byte[] password) {
		final byte[] hash = SHA1Hash(b0, password);
		return toText(hash);
	}
	
	public static String hashPasswordV2(String userId, String passwordHex) {
		final int id = Integer.parseInt(userId);
		byte[] passwordBytes = toHex(passwordHex);
		byte[] idBytes = new byte[4];
		// FIXME: assume little endian here!
		idBytes[0] = (byte)(id & 0xff);
		idBytes[1] = (byte)((id >> 8) & 0xff);
		idBytes[2] = (byte)((id >> 16) & 0xff);
		idBytes[3] = (byte)((id >> 24) & 0xff);
		return hashPasswordV1(idBytes, passwordBytes);
	}
	
	public static String hashPasswordV4(String userId, String password) {
		final String mid = hashPasswordV1(toByteArray(domain + ":"),
											toByteArray(password));
		if (userId != null && userId.length() > 0) {
			return hashPasswordV2(userId, mid);
		} else {
			return mid;
		}
	}
	
	public static void main(String[] args) throws Exception {
		Account user = new Account();
		user.userId = "";
		user.password = "kadmr2dwjx";
		user.mobileNumber = "15810396331";
		user.loginType = 1;
		user.captcha = null;
		user.configServersVersion = "0";
		Config.downloadConfiguration(user);
//		user.ssiAuthenticate();
		switch (user.loginStatus) {
		case 421:
		case 420:
			// TODO: handle captcha
			break;
		case 401:
		case 400:
			// TODO: handle login error
			break;
		}
	}
	
	public static Element getChildElement(Node node, String elementName) 
			throws FetionProtocolException {
		final Node child = node.getFirstChild();
		if (child == null || child.getNodeType() != Node.ELEMENT_NODE
				|| !child.getNodeName().equals(elementName)) {
			throw new FetionProtocolException(
					String.format("expected child element \"%\" not found", 
							elementName));
		}
		return (Element)child;
	}
}
